#include "mbcommunication.h"
#include "configs.h"
#include <QDebug>


MBCommunication::MBCommunication(MBCommunication::COMType types, SerialConfigs *serial, uint16_t *data)
{
    this->comtype=types;
    this->serial=serial;
    this->database=data;
    mb_mapping=NULL;
}

MBCommunication::~MBCommunication()
{
    modbus_close(mb);
    if(mb_mapping!=NULL)
        modbus_mapping_free(mb_mapping);
    modbus_free(mb);
}

void MBCommunication::run()
{
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
    int startAddr,length,rc,id,offset;
    uint16_t *saveAddr;
    QByteArray aa=serial->getSerialName().insert(0,"\\\\.\\").toLatin1();
    qDebug()<<aa;
    mb=modbus_new_rtu(aa,9600,serial->getSerialParity(),serial->getSerialDataBits(),serial->getSerialStopBits());
    modbus_set_slave(mb,1);
    modbus_connect(mb);
    struct timeval t;
    t.tv_sec=0;
    t.tv_usec=30000;   //设置modbus超时时间为300毫秒
    modbus_set_response_timeout(mb, &t);
    modbus_set_byte_timeout(mb,&t);
    modbus_set_debug(mb,true);
    modbus_set_error_recovery(mb,MODBUS_ERROR_RECOVERY_PROTOCOL);
    switch(comtype)
    {
    case COMInput:
    {
        while(1)
        {
            foreach(InputConfigs *ic,this->serial->inputs)
            {
                //modbus_connect(mb);
                startAddr=ic->getInputDataAddress();
                length=ic->getInputDataLength();
                saveAddr=(uint16_t *)this->database+ic->getInputSaveAddress();
                modbus_set_slave(mb,ic->getInputSlaveID());
                int ret=modbus_read_registers(mb,startAddr,length,saveAddr);
                qDebug()<<ret;
                if(ret>0)
                    ic->connected();
                else
                {
                    modbus_close(mb);
                    modbus_free(mb);
                    //free(mb);
                    mb=modbus_new_rtu(aa,9600,serial->getSerialParity(),serial->getSerialDataBits(),serial->getSerialStopBits());
                    modbus_set_slave(mb,1);
                    modbus_connect(mb);
                    struct timeval t;
                    t.tv_sec=0;
                    t.tv_usec=30000;   //设置modbus超时时间为300毫秒
                    modbus_set_response_timeout(mb, &t);
                    modbus_set_byte_timeout(mb,&t);
                    modbus_set_debug(mb,true);
                    modbus_set_error_recovery(mb,MODBUS_ERROR_RECOVERY_PROTOCOL);
                }
                modbus_flush(mb);
                //modbus_close(mb);
                msleep(100);
            }
        }
        break;
    }
    case COMOutput:
    {
        //id=serial->outputs[0]->getOutputSlaveID();
        for(int i=0;i<serial->outputs.count();i++)
        {
            map_outputs[serial->outputs[i]->getOutputSlaveID()]=serial->outputs[i];
        }

        mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                        MODBUS_MAX_READ_REGISTERS, 0);
        for(;;) {
            //memset(query,0,MODBUS_TCP_MAX_ADU_LENGTH);


            //rc = modbus_receive(mb, query);
            //rc=modbus_receive_confirmation(mb,query);
            rc = modbus_receive(mb, query);
            if (rc >= 0)
            {
                msleep(10);
                id=query[0];
                if(map_outputs[id]==NULL)
                    continue;
                else
                    offset=map_outputs[id]->getOutputDataAddress();
                modbus_set_slave(mb,id);
                //startAddr=query[2]<<8|query[3];
                startAddr=map_outputs[id]->getOutputStartAddr();
                length=query[4]<<8|query[5];
                memcpy(mb_mapping->tab_registers+startAddr,this->database+offset,length*2);
                int ret=modbus_reply(mb, query, 100, mb_mapping);
                if(ret>0)
                    map_outputs[id]->connected();
            }
            else
            {
                //int ret=modbus_reply(mb, query, 20, mb_mapping);
                qDebug()<<"faild "<< query[0]<<query[1]<<query[2]<<query[3]<<query[4]<<query[5];
            }
        }

        break;
    }
    }
}
